import pattern.circuit
import SocketServer
import gobject
import weakref, time, socket, select

class entry(pattern.circuit.Control):
	
	class EchoRequest(SocketServer.StreamRequestHandler):
		def handle(self):
			self.server.notify("on", self)
			self.line = ""
			gobject.io_add_watch(self.rfile, gobject.IO_IN | gobject.IO_HUP, self.readline)
			
		def poll(self, rfile):
			i, o, e = select.select([rfile], [], [rfile])
			return len(i) or len(e)
		
		def readline(self, source, condition):
			try:
				b = self.rfile.read(1)
				b += self.rfile.read(len(self.rfile._rbuf))
				if b == "":
					self.release()
					return False
				for c in b:
					if c in "\n\r":
						if self.line:
							self.server.process(self)
						self.line = ""
					else:
						self.line += c
				return True
			except:
				self.release()
				raise
			
		def release(self):
			self.server.notify("off", self)
			SocketServer.StreamRequestHandler.finish(self)
			print "Closed socket!"
			
		def finish(self): pass
		def __del__(self): self.release()
			
	def realize(self, event):
		if not hasattr(event.shape, 'port'): event.shape.port = 8889
		# Bring server up	
		try:
			self.connect(event.shape.port)
		except socket.error:
			print "Connection failed, retrying..."
			time.sleep(1)
			self.connect(event.shape.port)
		print "Server Hooked."
		self.s.notify = self.notify
		self.s.process = self.process
		self.realized = event
		self = weakref.ref(self)
		self().watch = gobject.io_add_watch(self().s.socket, gobject.IO_IN,
			lambda source, condition: self().incomingConnection(event))
				
	def connect(self, port):
		self.s = SocketServer.TCPServer(("", port), self.EchoRequest)

	def notify(self, op, request):
		self.realized.trail = request
		bridge = self.acquireInterface(self.realized, "community")
		del self.realized.trail
		if bridge is not None:
			bridge.push(op, request)

	def process(self, request):
		self.realized.trail = request
		bridge = self.acquireInterface(self.realized, "line out")
		del self.realized.trail
		if bridge is not None:
			bridge.push(request.line)
			
	def shutdown(self, event = None):
		try:
			del self.s
			gobject.source_remove(self.watch)
		except AttributeError:
			pass
	
	def incomingConnection(self, event):
		self.s.handle_request()
		return True
		
	def incoming(self, event):
		event.trail.wfile.write(str(event.data) + "\r\n")
		
	def please(self, event):
		return "Telnet Server"
		
	def __del__(self):
		# Safety precautions
		self.shutdown()
